#pragma once
#include <sys/epoll.h>
#include "Socket.hpp"
#include "Logger.hpp"

const static int gdefaultfd = -1;
const static int gsize = 64;

class EpollServer
{
public:
    EpollServer(uint16_t port) : _listenfd(std::make_unique<TcpSocket>()), _epollfd(gdefaultfd)
    {
        _listenfd->BuildTcpSocket(port);
        _epollfd = epoll_create(1024);
        if (_epollfd < 0)
        {
            LOG(LogLevel::FATAL) << "epoll create erro";
            return;
        }
        LOG(LogLevel::INFO) << "epoll create success";
        struct epoll_event ev;
        ev.events = EPOLLIN | EPOLLET;
        ev.data.fd = _listenfd->SockFd();
        int n = epoll_ctl(_epollfd, EPOLL_CTL_ADD, _listenfd->SockFd(), &ev);
        if (n < 0)
        {
            LOG(LogLevel::ERRO) << "添加fd: " << _listenfd->SockFd() << "失败";
            return;
        }
        LOG(LogLevel::INFO) << "添加fd: " << _listenfd->SockFd() << "成功";
    }
    void Accepter()
    {
        InetAddr clientaddr;
        int fd = _listenfd->Accept(&clientaddr);
        if (fd > 0)
        {
            LOG(LogLevel::INFO) << "accept success,fd is " << clientaddr.ToString();
            struct epoll_event ev;
            ev.events = EPOLLIN;
            ev.data.fd = fd;
            int n = epoll_ctl(_epollfd, EPOLL_CTL_ADD, fd, &ev);
            if (n < 0)
            {
                LOG(LogLevel::ERRO) << "添加fd: " << _listenfd->SockFd() << "失败";
                return;
            }
            LOG(LogLevel::INFO) << "添加fd: " << _listenfd->SockFd() << "成功";
        }
    }
    void Recver(int fd)
    {
        char buffer[1024];
        buffer[0]=0;
        ssize_t n=recv(fd,buffer,sizeof(buffer),0);
        if(n>0)
        {
            buffer[n]=0;
            std::cout<<"client to say# "<<buffer;
            std::string echo_str="echo server@ ";
            echo_str+=buffer;
            send(fd,echo_str.c_str(),echo_str.size(),0);
        }
        else if(n==0)
        {
            LOG(LogLevel::WARING)<<"client quit,me too,fd is "<<fd;
            int n=epoll_ctl(_epollfd,EPOLL_CTL_DEL,fd,nullptr);
            if (n < 0)
            {
                LOG(LogLevel::ERRO) << "删除fd: " << fd << "失败";
                return;
            }
            LOG(LogLevel::INFO) << "删除fd: " << fd << "成功";
            close(fd);
        }
        else
        {
            LOG(LogLevel::ERRO)<<"Recver fd "<<fd<<"失败";
            int n=epoll_ctl(_epollfd,EPOLL_CTL_DEL,fd,nullptr);
            if (n < 0)
            {
                LOG(LogLevel::ERRO) << "删除fd: " << fd << "失败";
                return;
            }
            LOG(LogLevel::INFO) << "删除fd: " << fd << "成功";
            close(fd);
        }
    }

    void Dispatcher(int num)
    {
        LOG(LogLevel::INFO) << "有新事件就绪了...";
        for (int i = 0; i < num; i++)
        {
            int fd = _revs[i].data.fd;
            uint32_t event = _revs[i].events;
            if (event & EPOLLIN)
            {
                if (fd == _listenfd->SockFd())
                {
                    Accepter();
                }
                else
                {
                    Recver(fd);
                }
            }
            // TODO
        }
    }
    void Run()
    {
        while (true)
        {
            int timeout = -1;
            int n = epoll_wait(_epollfd, _revs, gsize, timeout);
            switch (n)
            {
            case 0:
                LOG(LogLevel::WARING) << "timeout...";
                break;
            case -1:
                LOG(LogLevel::ERRO) << "epoll erro...";
                break;
            default:
                Dispatcher(n);
                break;
            }
        }
    }
    ~EpollServer()
    {
    }

private:
    std::unique_ptr<Socket> _listenfd;
    int _epollfd;
    struct epoll_event _revs[gsize];
};